package com.seattleweb.gdocdump;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.gnome.gtk.Entry;
import org.gnome.gtk.ProgressBar;

import com.google.gdata.client.GoogleAuthTokenFactory.UserToken;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.MediaContent;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.data.extensions.LastModifiedBy;
import com.google.gdata.data.media.MediaSource;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class Dumper extends Thread {

    private String username;
    private String password;

    static DocsService service = null;
    static SpreadsheetService spread_client = null;
    
    Entry entryPassword = new Entry();
    Entry entryUsername = new Entry();
    
    public String workingDir;
    ProgressBar progressBar;

    public Dumper(ProgressBar progressBar) {
	this.progressBar = progressBar;

	   workingDir = System.getProperty("user.home")+"/Documents/Backup/GoogleDocs";
	      System.out.println("working Directory: " + workingDir);

	    boolean success = (new File(workingDir)).mkdirs();
	    if (success) {
	      System.out.println("Directory: " + workingDir + " created");
	    }    
	  	
    }

    public void authenticate(String username, String password)
	    throws AuthenticationException {
	this.username = username;
	this.password = password;

	service = new DocsService("gdocdump");
	service.setUserCredentials(username, password);
    }

    public void run() {

	try {

	    progressBar.setFraction(0.0);
	    URL feedUri = new URL(
		    "http://docs.google.com/feeds/default/private/full/");

	    DocumentListFeed feed = service.getFeed(feedUri,
		    DocumentListFeed.class);

	    int docCount = feed.getEntries().size();
	    int i=0;
	    
	    for (DocumentListEntry entry : feed.getEntries()) {

		i++;
		progressBar.setText("Dumping doc " + i+ " of "+docCount);
		
		
		String resourceId = entry.getResourceId();
		String docType = resourceId.substring(0, resourceId
			.lastIndexOf(':'));

		String title = entry.getTitle().getPlainText();

		System.out.println("\n\nresourceId: " + resourceId);
		System.out.println("title: " + title);
		System.out.println("docType: " + docType);
		
		if ("document".equals(docType)) {
		    downloadDocument(resourceId, workingDir+"/" + title + ".doc");
		}
		
		if ("presentation".equals(docType)) {
		    downloadDocument(resourceId, workingDir+"/" + title + ".ppt");
		}

		else if ("spreadsheet".equals(docType)) {

		    SpreadsheetService spread_client = new SpreadsheetService("gdocdump");
		    spread_client.setUserCredentials(username, password);

		    // Substitute the spreadsheets token for the docs token
		    UserToken docsToken = (UserToken) service
			    .getAuthTokenFactory().getAuthToken();
		    UserToken spreadsheetsToken = (UserToken) spread_client
			    .getAuthTokenFactory().getAuthToken();
		    service.setUserToken(spreadsheetsToken.getValue());

		    downloadSpreadsheet(entry, workingDir+"/" + title + ".xls");
		    service.setUserToken(docsToken.getValue());

		} else if ("pdf".equals(docType)) {
		    downloadPDF(resourceId, workingDir+"/" + title+".pdf");
		}
		
		double fraction = (double)i / (double)docCount;
		progressBar.setFraction(fraction);
	    }
	    
	    System.out.println("done dumping");
	    
	    progressBar.setText(docCount+" documents dumped");
	    
	} catch (Exception e) {
	    e.printStackTrace();

	}

    }


    public void downloadFile(String exportUrl, String filepath)
	    throws IOException, MalformedURLException, ServiceException {
	System.out.println("Exporting document from: " + exportUrl);

	MediaContent mc = new MediaContent();
	mc.setUri(exportUrl);
	MediaSource ms = service.getMedia(mc);

	InputStream inStream = null;
	FileOutputStream outStream = null;

	try {
	    inStream = ms.getInputStream();
	    outStream = new FileOutputStream(filepath);

	    int c;
	    while ((c = inStream.read()) != -1) {
		outStream.write(c);
	    }
	} finally {
	    if (inStream != null) {
		inStream.close();
	    }
	    if (outStream != null) {
		outStream.flush();
		outStream.close();
	    }
	}
    }

    public void downloadSpreadsheet(String resourceId, String filepath)
	    throws IOException, MalformedURLException, ServiceException {
	String docId = resourceId.substring(resourceId.lastIndexOf(":") + 1);
	String fileExtension = filepath
		.substring(filepath.lastIndexOf(".") + 1);
	String exportUrl = "http://spreadsheets.google.com/feeds/download/spreadsheets"
		+ "/Export?key=" + docId + "&exportFormat=" + fileExtension;

	// If exporting to .csv or .tsv, add the gid parameter to specify which
	// sheet to export
	if (fileExtension.equals("csv") || fileExtension.equals("tsv")) {
	    exportUrl += "&gid=0"; // gid=0 will download only the first sheet
	}

	downloadFile(exportUrl, filepath);
    }

    public void downloadSpreadsheet(DocumentListEntry entry,
	    String filepath) throws IOException, MalformedURLException,
	    ServiceException {
	String fileExtension = filepath
		.substring(filepath.lastIndexOf(".") + 1);
	String exportUrl = ((MediaContent) entry.getContent()).getUri()
		+ "&exportFormat=" + fileExtension;

	// If exporting to .csv or .tsv, add the gid parameter to specify which
	// sheet to export
	if (fileExtension.equals("csv") || fileExtension.equals("tsv")) {
	    exportUrl += "&gid=0"; // gid=0 will download only the first sheet
	}

	downloadFile(exportUrl, filepath);
    }

    public void downloadPDF(DocumentListEntry entry, String filepath)
	    throws MalformedURLException, IOException, ServiceException {
	MediaContent mc = (MediaContent) entry.getContent();
	String fileExtension = mc.getMimeType().getSubType();
	String exportUrl = mc.getUri();

	// PDF file cannot be exported in different formats.
	String requestedExtension = filepath.substring(filepath
		.lastIndexOf(".") + 1);
	if (!requestedExtension.equals(fileExtension)) {
	    System.err.println("Warning: " + mc.getMimeType().getMediaType()
		    + " cannot be downloaded as a " + requestedExtension
		    + ". Using ." + fileExtension + " instead.");
	    filepath = filepath.substring(0, filepath.lastIndexOf(".") + 1)
		    + fileExtension;
	}

	downloadFile(exportUrl, filepath);
    }

    public void downloadPDF(String resourceId, String filepath)
	    throws MalformedURLException, IOException, ServiceException {
	// First, fetch entry using the resourceId
	URL url = new URL("http://docs.google.com/feeds/default/private/full/"
		+ resourceId);
	DocumentListEntry entry = service
		.getEntry(url, DocumentListEntry.class);
	downloadPDF(entry, filepath);
    }

    public void downloadDocument(String resourceId, String filepath)
	    throws IOException, MalformedURLException, ServiceException {
	String docId = resourceId.substring(resourceId.lastIndexOf(":") + 1);
	String fileExtension = filepath
		.substring(filepath.lastIndexOf(".") + 1);
	String exportUrl = "http://docs.google.com/feeds/download/documents/Export?docId="
		+ docId + "&exportFormat=" + fileExtension;
	downloadFile(exportUrl, filepath);
    }

    public void downloadDocument(DocumentListEntry entry, String filepath)
	    throws IOException, MalformedURLException, ServiceException {
	String fileExtension = filepath
		.substring(filepath.lastIndexOf(".") + 1);
	String exportUrl = ((MediaContent) entry.getContent()).getUri()
		+ "&exportFormat=" + fileExtension;
	downloadFile(exportUrl, filepath);
    }

}